﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpShare.Storage.Security;
using SharpShare.Storage.Searching;
using SharpShare.Utilities;

namespace SharpShare.Storage {
    [Flags]
    public enum StorageItemAttributes {
        None = 0,
        Hidden = 2
    }

    /// <summary>
    /// Represents a storage item entity.
    /// </summary>
    /// <remarks>
    /// Storage items extend ICastable<> for IStorageContainer and IStorageFile. This allows storage items to easily be asked
    /// if they represent a file or container by matter of using the Castable construct.
    /// 
    /// For example, if you have an IStorageItem instance and need to see if the storage item represents a file, you can call
    /// <code><![CDATA[
    /// IStorageFile file = storageItem.AsFile();
    /// ]]></code>
    /// If 'file' is not null, you can use it to access file services represented by the storage item.  If it is null, the storage item
    /// is not a file.
    /// 
    /// The returned object doesn't necesarily have to be the same reference (this). However, the returned object should have 
    /// the same results when calling Object.Equals and Object.GetHashCode on the original object.
    /// </remarks>
    public interface IStorageItem : ICastable<IStorageContainer>, ICastable<IStorageFile> {
        /// <summary>
        /// Gets the name of this storage item.
        /// </summary>
        string Name { get; }

        /// <summary>
        /// Gets the storage container which contains this storage item.
        /// </summary>
        IStorageContainer Parent { get; }

        /// <summary>
        /// True if this storage item still exists, otherwise False.
        /// </summary>
        bool Exists { get; }

        /// <summary>
        /// Gets or sets attributes for this storage item.
        /// </summary>
        StorageItemAttributes Attributes { get; set; }

        /// <summary>
        /// Gets the date this storage item was created.
        /// </summary>
        DateTime DateCreated { get; set; }

        /// <summary>
        /// Gets the date this storage item was modified.
        /// </summary>
        DateTime DateModified { get; set; }

        /// <summary>
        /// Opens a metadata stream with the given name, access, and share modes.
        /// </summary>
        /// <param name="name">The name of the metadata stream to open.</param>
        /// <param name="mode">The mode for which to open the metadata stream.</param>
        /// <param name="access">The access mode of the metadata stream.</param>
        /// <param name="share">The share mode of the metadata stream.</param>
        /// <returns>
        /// An instance of IStorageDataProvider used to access the contents of the metadata stream.
        /// If mode is OpenExisting and a metadata stream does not exist, returns null.
        /// </returns>
        IStorageDataProvider OpenMetadata(string name, StorageFileAccess access, StorageFileAccess share, StorageFileMode mode = StorageFileMode.OpenOrCreate);

        /// <summary>
        /// Deletes a metadata stream with the given name.
        /// </summary>
        /// <param name="name">The name of the metadata stream to delete.</param>
        /// <returns>True if the metadata was found and deleted, otherwise False.</returns>
        bool RemoveMetadata(string name);

        /// <summary>
        /// Gets a sequence of metadata names on this storage item.
        /// </summary>
        IEnumerable<string> ListMetadata();

        /// <summary>
        /// Deletes this storage item.
        /// </summary>
        void Delete();

        /// <summary>
        /// Moves this storage item to another container.
        /// </summary>
        /// <param name="container"></param>
        void Move(IStorageContainer container, string newNameOrNull);

        /// <summary>
        /// Gets the access rules describing what this storage item is capable of.
        /// </summary>
        /// <remarks>
        /// For example, if this storage item is incapable of being deleted because of backing store constraints,
        /// the access list should contain an entry for Deny Delete.  This access list is the very last one to be
        /// added to the overall access list.  Therefore, any Allow entries in this list will always prevail.
        /// 
        /// Return StorageAccessList.Empty if the storage item doesn't have any access restrictions.
        /// </remarks>
        StorageAccessList AvailableAccess { get; }
    }
}
